package com.vita.bduck.logger;

import android.content.Context;
import com.vita.bduck.bitmap.utils.StorageUtils;

import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;

/**
 * 记录未抓取的异常
 * Created with IntelliJ IDEA.
 * User: Vita Hao
 * Date: 13-6-19
 * Time: 上午10:21
 * To change this template use File | Settings | File Templates.
 */
public class LogCrashHandler implements Thread.UncaughtExceptionHandler {
    private final Context context;

    private static final String TAG = LogConstant.LOG_TAG;
    /**
     * 日志写出的路径
     */
    protected static String logPath = null;

    /**
     * 是否为DEBUG模式
     */
    protected static boolean mIsDebug = true;

    /**
     * 是否显示在LogCat上
     */
    protected static boolean mIsInLogCat = true;

    /**
     * 是否写在文件上
     */
    protected static boolean mIsInFile = false;


    /**
     * 输出log flags,默认输出debug, warning, error
     */
    protected static int mFlags = -1;

    /**
     * 监听UncaughtException
     */
    private IUncaughtException mListener = null;

    /**
     * 最大log存储容量
     */
    protected static long maxLogSize = 0L;

    /**
     * 监听UncaughtException
     */
    interface IUncaughtException {
        void LogUncaughtCallback(String Tag, String msg);
    }


    /**
     * 系统默认的UncaughtException处理类
     */
    private Thread.UncaughtExceptionHandler mDefaultHandler = null;


    private LogCrashHandler(final Builder builder) {
        context = builder.context;
        logPath = builder.logPath;
        mIsDebug = builder.mIsDebug;
        mIsInLogCat = builder.mIsInLogCat;
        mIsInFile = builder.mIsInFile;
        mFlags = builder.mFlags;
        mListener = builder.mListener;
        maxLogSize = builder.maxLogSize;
    }

    /**
     * 设置UncaughtExceptionHandler
     */
    public void initUncaughtException() {
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    public void unInitUncaughtException() {
        if (mDefaultHandler == null) {
            mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        }
        Thread.setDefaultUncaughtExceptionHandler(mDefaultHandler);
    }

    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {

        // 自己处理
        handleException(throwable);

        if (mDefaultHandler != null) {
            // 让系统默认的异常处理器来处理
            mDefaultHandler.uncaughtException(thread, throwable);
        }

        // 睡眠下，以便能写出数据
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            android.util.Log.e(TAG, "error : ", e);
        }

        // 退出程序
        android.os.Process.killProcess(android.os.Process.myPid());
        System.exit(1);
    }

    /**
     * 处理异常
     *
     * @param ex
     * @return
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        if (mListener != null) {
            mListener.LogUncaughtCallback(TAG, getErrorInfo(ex));
        } else {
            android.util.Log.w(TAG, "not set listener");
        }
        return true;
    }

    /**
     * 获取错误信息
     *
     * @param ex
     * @return
     */
    private String getErrorInfo(Throwable ex) {
        Writer writer = new StringWriter();
        PrintWriter pw = new PrintWriter(writer);
        ex.printStackTrace(pw);
        pw.close();
        String error = writer.toString();
        return error;
    }

    /**
     * 默认异常监听器
     */
    protected static IUncaughtException defaultUncaughException = new IUncaughtException() {
        @Override
        public void LogUncaughtCallback(String Tag, String msg) {
            StringBuilder sb = new StringBuilder();
            sb.append("[f:]\t");
            sb.append("Tag:");
            sb.append(Tag);
            Log.writeToLog("f", sb.toString(), msg);
        }
    };

    /**
     * 配置构造器，如果没有任何参数，调用默认方法
     */
    public static class Builder {

        private Context context;

        /**
         * 日志写出的路径
         */
        private static String logPath = null;

        /**
         * 是否为DEBUG模式
         */
        private static boolean mIsDebug = false;

        /**
         * 是否显示在LogCat上
         */
        private static boolean mIsInLogCat = true;

        /**
         * 是否写在文件上
         */
        private static boolean mIsInFile = false;

        /**
         * 输出log flags,默认输出debug, warning, error
         */
        private static int mFlags = -1;

        /**
         * 最大log存储容量
         */
        private static long maxLogSize = 0L;

        /**
         * 监听UncaughtException
         */
        private static IUncaughtException mListener = null;


        public Builder(Context context) {
            this.context = context.getApplicationContext();
        }

        public LogCrashHandler build() {
            initEmptyFiledsWithDefaultValues();
            return new LogCrashHandler(this);
        }

        /**
         * 是否显示在LogCat上
         *
         * @param mIsInLogCat
         * @return
         */
        public Builder enableLogcat(boolean mIsInLogCat) {
            this.mIsInLogCat = mIsInLogCat;
            return this;
        }

        /**
         * 是否写在文件上
         */
        public Builder enableWriteFile(boolean mIsInFile) {
            this.mIsInFile = mIsInFile;
            return this;
        }

        /**
         * 日志记录路径,如果enableWriteFile为false无效
         *
         * @return
         */
        public Builder logPath(String logPath) {
            File f =  StorageUtils.getOwnCacheDirectory(context,logPath);
            if(f != null){
                this.logPath =f.getPath();
            }

            return this;
        }

        /**
         * 显示debug模式
         *
         * @param mIsDebug
         * @return
         */
        public Builder debug(boolean mIsDebug) {
            this.mIsDebug = mIsDebug;
            return this;
        }

        /**
         * 输出log flags,默认输出debug, warning, error
         * @return
         */
        public Builder setLgLevelFlag(int mFlags){
            this.mFlags = mFlags;
            return this;
        }

        public Builder setMaxLogSize(long maxLogSize) {
            this.maxLogSize = maxLogSize;
            return this;
        }

        private void initEmptyFiledsWithDefaultValues() {
            if (logPath == null) {
                logPath = StorageUtils.getCacheDirectory(context).getPath();
            }
            if(mListener == null){
                mListener = defaultUncaughException;
            }
            if(mFlags == -1){
                //默认输出debug, warning, error
                mFlags = LogConstant.LOG_D | LogConstant.LOG_W | LogConstant.LOG_E;
            }
            if(maxLogSize <= 0){
                maxLogSize = LogConstant.MAX_LOGSIZE;
            }
        }
    }

}
